`include "PRV564Config.v"
`include "PRV564Define.v"
//       中断控制单元，包含status、isa、edeleg、ideleg、ie、tvec、counteren
module TrapSetup(
    input wire              CLKi, ARSTi,        //clock and global reset 
    //-----------CSR value output----------
    output wire [`XLEN-1:0] mstatus, misa, mie, mcounteren,    //M莫斯Trap管理寄存器
    output wire [`XLEN-1:0] sstatus,       sie, scounteren,    //S模式Trap管理寄存器
    output reg  [`XLEN-1:0] mtvec, stvec, mideleg, medeleg,
    output  reg [1:0]       privilege,                                                  //current privilege
    //-----------write back to csr---------
    input wire [11:0]       csr_index,
    input wire [`XLEN-1:0]  csr_data,
    input wire              csr_wren,
    //------------return--------------------
    input wire              mret, sret,
    //-----------trap-----------------------
    input wire              trap_s, trap_m       //trap targert to M or S mode
);

//---------------mstatus and sstatus---------------------
    reg         status_tsr,     status_tw,      status_tvm, status_mxr, status_sum, status_mpriv, status_spp;
    reg         status_mpie,    status_spie,    status_mie, status_sie, status_sd;
    reg [1:0]   status_mpp,     status_fs,      status_uxl, status_sxl; 
always@(posedge CLKi or posedge ARSTi)begin
    if(ARSTi)begin
        status_tsr  <= 1'b0;
        status_tw   <= 1'b0;
        status_tvm  <= 1'b0;
        status_mxr  <= 1'b0;
        status_sum  <= 1'b0;
        status_mpriv<= 1'b0;
        status_mpp  <= 2'b00;
        status_spp  <= 1'b0;
        status_mpie <= 1'b0;
        status_spie <= 1'b0;
        status_mie  <= 1'b0;
        status_sie  <= 1'b0;
        privilege   <= `Machine;
    end
    else if(csr_wren)begin
        if(csr_index == `mrw_mstatus_index)begin        //write to mstatus\
            status_sxl  <= csr_data[35:34];
            status_uxl  <= csr_data[33:32];
            status_tsr  <= csr_data[22];
            status_tw   <= csr_data[21];
            status_tvm  <= csr_data[20];
            status_mxr  <= csr_data[19];
            status_sum  <= csr_data[18];
            status_mpriv<= csr_data[17];
            status_fs   <= csr_data[14:13];
            status_mpp  <= csr_data[12:11];
            status_spp  <= csr_data[8];
            status_mpie <= csr_data[7];
            status_spie <= csr_data[5];
            status_mie  <= csr_data[3];
            status_sie  <= csr_data[1];
        end
        else if(csr_index == `srw_sstatus_index)begin   //write to sstatus
            status_uxl  <= csr_data[33:32];
            status_mxr  <= csr_data[19];
            status_sum  <= csr_data[18];
            status_fs   <= csr_data[14:13];
            status_spp  <= csr_data[8];
            status_spie <= csr_data[5];
            status_sie  <= csr_data[1];
        end
    end
    else if(mret)begin
        status_mie <= status_mpie;
        status_mpie<= 1'b1;
        status_mpp <= 2'b00;
        privilege  <= status_mpp;
    end
    else if(sret)begin
        status_sie <= status_spie;
        status_spie<= 1'b1;
        status_spp <= 1'b0;
        privilege  <= status_spp ? `Supervisior : `User;
    end
    else if(trap_m)begin                    //跳转到M模式进行处理
        status_mpie<= status_mie;
        status_mie <= 1'b0;
        status_mpp <= privilege;
        privilege  <= `Machine;
    end
    else if(trap_s)begin                    //跳转到S模式进行处理
        status_spie<= status_sie;
        status_sie <= 1'b0;
        status_spp <= privilege[0];
        privilege  <= `Supervisior;
    end
end
always@(*)begin
    status_sd = (status_fs==2'b11);
end
//status register:
//         bit:   |   63   |62:38| 37 | 36 |   35:34  |   33:32  |31:23|    22   |   21    |    20    |    19    |    18    |      17    |16:15| 14:13  |  12:11   |10:9|    8      |     7     |  6 |     5     |  4 |    3     |  2 |    1     | 0
//    function:   |   SD   |WPRI | MBE| SBE|    SXL   |    UXL   |WPRI |   TSR   |   TW    |    TVM   |   MXR    |    SUM   |     MPRV   | XS  |   FS   |   MPP    |MPRI|    SPP    |    MPIE   | UBE|    SPIE   |WPRI|    MIE   |WPRI|    SIE   |WPRI
assign mstatus = {status_sd,25'b0,1'b0,1'b0,status_sxl,status_uxl,9'b0,status_tsr,status_tw,status_tvm,status_mxr,status_sum,status_mpriv,2'b0,status_fs,status_mpp,2'b00,status_spp,status_mpie,1'b0,status_spie,1'b0,status_mie,1'b0,status_sie,1'b0};
assign sstatus = {status_sd,         29'b0            ,status_uxl,                 12'b0              ,status_mxr,status_sum,     1'b0   ,2'b0,status_fs,   2'b0   ,2'b00,status_spp,        2'b0    ,status_spie,        3'b0        ,status_sie,1'b0};
//-----------------mie & sie--------------------
    reg ie_msie, ie_mtie, ie_meie;
    reg ie_ssie, ie_stie, ie_seie;
always@(posedge CLKi or posedge ARSTi)begin
    if(ARSTi)begin
        ie_ssie<=	'b0;
		ie_msie<=	'b0;
		ie_stie<=	'b0;
		ie_mtie<=	'b0;
		ie_seie<=	'b0;
		ie_meie<=   'b0;
    end
    else if(csr_wren)begin
        if(csr_index == `mrw_mie_index)begin
            ie_ssie<=	csr_data[1];
		    ie_msie<=	csr_data[3];
		    ie_stie<=	csr_data[5];
		    ie_mtie<=	csr_data[7];
		    ie_seie<=	csr_data[9];
		    ie_meie<=   csr_data[11];
        end
        else if(csr_index == `srw_sie_index)begin
            ie_ssie<=	csr_data[1];
		    ie_stie<=	csr_data[5];
		    ie_seie<=	csr_data[9];
        end
    end
end
assign mie = {52'b0,ie_meie,1'b0,ie_seie,1'b0,ie_mtie,1'b0,ie_stie,1'b0,ie_msie,1'b0,ie_ssie,1'b0};
assign sie = {54'b0,ie_seie,3'b0,ie_stie,3'b0,ie_ssie,1'b0};
//---------------mtvec and stvec-----------------

always@(posedge CLKi or posedge ARSTi)begin
    if(ARSTi)begin
        stvec <= 'h0;
        mtvec <= 'h0;
    end
    else if(csr_wren)begin
        if(csr_index == `mrw_mtvec_index)begin
            mtvec <= csr_data;
        end
        else if(csr_index == `srw_stvec_index)begin
            stvec <= csr_data;
        end
    end
end
//----------------ideleg and edeleg----------------
always@(posedge CLKi or posedge ARSTi)begin
    if(ARSTi)begin
        mideleg <= 'h0;
        medeleg <= 'h0;
    end
    else if(csr_wren)begin
        if(csr_index == `mrw_medeleg_index)begin
            medeleg <= csr_data;
        end
        else if(csr_index == `mrw_mideleg_index)begin
            mideleg <= csr_data;
        end
    end
end

//---------------counteren---------------------------
reg mcounteren_CY, mcounteren_TM, mcounteren_IR;
reg scounteren_CY, scounteren_TM, scounteren_IR;
always@(posedge CLKi or posedge ARSTi)begin
    if(ARSTi)begin
        mcounteren_CY <= 1'b0;
        mcounteren_TM <= 1'b0;
        mcounteren_IR <= 1'b0;
        scounteren_CY <= 1'b0;
        scounteren_TM <= 1'b0;
        scounteren_IR <= 1'b0;
    end
    else if(csr_wren)begin
        if(csr_index == `mrw_mcounteren_index)begin
            mcounteren_CY <= csr_data[0];
            mcounteren_TM <= csr_data[1];
            mcounteren_IR <= csr_data[2];
        end
        else if(csr_index == `srw_scounteren_index)begin
            scounteren_CY <= csr_data[0];
            scounteren_TM <= csr_data[1];
            scounteren_IR <= csr_data[2];
        end
    end
end
assign mcounteren = {61'b0, mcounteren_IR, mcounteren_TM, mcounteren_CY};
assign scounteren = {61'b0, scounteren_IR, scounteren_TM, scounteren_CY};
assign misa       = 64'b00000000_00000000_00000000_00000000_00000000_00001010_00000001_00000001;
//					_____________________________________________________U_S_____M___I________A

endmodule
